package main

import "fmt"

func main() {
	ps5MachinePlus := PS5MachinePlus{}
	ps5MachinePlus.SetPS5Machine(&PS5WithCD{})

	ps5MachinePlus.StartGPUEngine()
	price := ps5MachinePlus.GetPrice()
	fmt.Printf("PS5 CD 豪华Plus版，价格: %d 元\n\n", price)

	ps5WithTopicColor := PS5WithTopicColor{}
	ps5WithTopicColor.SetPS5Machine(&ps5MachinePlus)
	ps5WithTopicColor.StartGPUEngine()
	price = ps5WithTopicColor.GetPrice()
	fmt.Printf("PS5 CD 豪华Plus 经典主题配色版，价格: %d 元\n", price)
}

/*
装饰器模式（Decorator Pattern）也叫作包装器模式（Wrapper Pattern）
指在不改变原有对象的基础上，动态地给一个对象添加一些额外的职责
就增加功能来说，装饰器模式相比生成子类更为灵活，属于结构型设计模式。
*/

/*
客户端：会用多层装饰器来封装组件， 最后调用装饰好的包装器的方法，启动执行。
组件接口：Component声明装饰器对象和被装饰的组件对象要实现的公用接口。
组件实现：具体的组件实现类它的Operation方法中定义了组件的基础行为， 装饰类可以增强这些行为。
基础装饰类：拥有一个指向被封装对象的成员变量。 在自己的Operation方法中调用被装饰对象的Operation方法
具体装饰类：重写父类的Operation方法实现增强逻辑。类图里已经给出了要实现的主要逻辑，第四步的基础装饰类并不需要一定存在，完全可以由具体装饰类来持有对被装饰对象的引用，并实现增强逻辑，这样一来整体的结构会更简单一些。
*/

type PS5 interface {
	StartGPUEngine()
	GetPrice() int
}

type PS5WithCD struct{}

func (p *PS5WithCD) StartGPUEngine() {
	fmt.Println("start engine")
}

func (p *PS5WithCD) GetPrice() int {
	return 5000
}

type PS5WithGigital struct{}

func (p *PS5WithGigital) StartGPUEngine() {
	fmt.Println("start normal gpu engine")
}

func (p *PS5WithGigital) GetPrice() int {
	return 3600
}

type PS5MachinePlus struct {
	ps5Machine PS5
}

func (p *PS5MachinePlus) SetPS5Machine(ps5 PS5) {
	p.ps5Machine = ps5
}

func (p *PS5MachinePlus) StartGPUEngine() {
	p.ps5Machine.StartGPUEngine()
	fmt.Println("start plus plugin")
}

func (p *PS5MachinePlus) GetPrice() int {
	return p.ps5Machine.GetPrice() + 500
}

type PS5WithTopicColor struct {
	ps5Machine PS5
}

func (p *PS5WithTopicColor) SetPS5Machine(ps5 PS5) {
	p.ps5Machine = ps5
}

func (p *PS5WithTopicColor) StartGPUEngine() {
	p.ps5Machine.StartGPUEngine()
	fmt.Println("尊贵的主题色主机，GPU启动")
}
func (p *PS5WithTopicColor) GetPrice() int {
	return p.ps5Machine.GetPrice() + 200
}

/*
装饰器模式就是代理模式的一个特殊应用。
装饰器模式强调自身功能的扩展。
代理模式强调对代理过程的控制。
*/

/*
装饰器 VS 职责链模式
装饰器和职责链在行为上看都是多个单元进行组合完成逻辑处理，但是装饰器注重给某样东西添加扩展，最终会得到一个产品。而职责链更强调分步骤完成某个流程，更像是一个任务链表，而且与装饰器模式不同的是，职责链可以随时终止。

举个例子来说，针对OA系统请假审批这个场景，假设员工请假需要得到组长、总监和经理的批准才行。在这种情况下，使用装饰器模式实现的话无论您的请假在前面的环节被批准还是被拒绝，整个链条都不会中断，最终我们会得到三个级别审批人对申请的全部反馈。

而使用职责链模式的话，在每个阶段，每个审批人都有权批准或拒绝。如果请求在任何级别被拒绝，那么整个流程就会结束，请求不会继续流转到下一个级别的审批人那里。
*/
